package com.yushu.common.config.shiro;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.yushu.authority.pojo.bo.PmRole;
import com.yushu.authority.pojo.bo.PmUser;
import com.yushu.authority.pojo.vo.PmUserVO;
import com.yushu.authority.service.PmRoleService;
import com.yushu.authority.service.PmUserService;
import com.yushu.common.execption.CgException;
import com.yushu.common.util.bean.Father2Son;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
/**
 * @author test
 * @CreateDate 2020-12-03 15:47:25
 */
public class ShiroRealm extends AuthorizingRealm {
    /*

     *//**
     * 认证
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     *//*
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        String username = usernamePasswordToken.getUsername();
        char[] password0 = usernamePasswordToken.getPassword();
        if (null == password0) {
            return null;
        } else {
            String password = new String(password0);
            if (!"qiuyuchun@163.com".equals(username) || !"loveme287250".equals(password)) {
                throw new RuntimeException("用户名或密码错误");
            }
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());
            return info;
        }


    }


    */
    /**
     * 授权检查
     *
     * @param principalCollection
     * @return
     *//*
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 简单授权信息对象，对象中包含用户的角色和权限信息
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRole("admin");
        info.addStringPermission("cms:news:view");
        info.addStringPermission("cms:news:list");
        System.out.println("授权完成....");
        return info;
    }*/
    private static final Logger logger = LoggerFactory.getLogger(ShiroRealm.class);


    @Autowired
    private PmRoleService roleService;
    @Autowired
    private PmUserService userService;


    /**
     * 获取身份信息，我们可以在这个方法中，从数据库获取该用户的权限和角色信息
     * 当调用权限验证时，就会调用此方法
     * 授权
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        PmUserVO pmUser = (PmUserVO) getAvailablePrincipal(principalCollection);

        PmRole role = null;
        SimpleAuthorizationInfo info = null;
        try {
            EntityWrapper userWrapper = new EntityWrapper<PmUser>();
            userWrapper.eq("user_name", pmUser.getUserName());
            PmUser user = userService.selectOne(userWrapper);


            EntityWrapper roleWrapper = new EntityWrapper<PmUser>();
            roleWrapper.eq("user_name", pmUser.getUserName());
            List<PmRole> roleList = roleService.selectRolesByUserId("",user.getId());

            if (roleList.size() > 0) {
                String[] roleIds = new String[roleList.size()];
                for (int i = 0; i < roleList.size(); i++) {
                    PmRole roleOnList = roleList.get(i);
                    roleIds[i] = roleOnList.getId();
                }
                /*List<PmPermission> permissions = permissionService.selectPermissionsByRoleId(roleIds);
                HashSet<String> permissionSet = new HashSet<>();
                if (permissions.size() > 0) {
                    for (int i = 0; i < permissions.size(); i++) {
                        PmPermission permissionOnList = permissions.get(i);
                        permissionSet.add(permissionOnList.getPermissionSign());
                    }
                }
//                通过用户查询当前用的角色下的搜索框权限
                List<PmSearchBoxPermissions> searchBOxList = pmSearchBoxPermissionsService.selectSearchBoxList(pmUser);

                if (searchBOxList.size() > 0) {
                    for (int i = 0; i < searchBOxList.size(); i++) {
                        PmSearchBoxPermissions boxPermission = searchBOxList.get(i);
                        permissionSet.add(boxPermission.getName());
                    }
                }*/
//                System.out.println(JSON.toJSON(permissionSet));

                info = new SimpleAuthorizationInfo();
//                info.setStringPermissions(permissionSet);


            }

        } catch (Exception e) {
            e.printStackTrace();
        }


        return info;
    }

    /**
     * 在这个方法中，进行身份验证
     * login时调用，认证
     * 获取认证消息，如果数据库中没有数据，返回null
     * 如果用户名，密码正确，则返回正确的对象
     * <p>
     * SimpleAuthenticationInfo 可以封装正确的用户名和密码
     * token（象征代表） 是我们需要认证的token
     * AuthenticationToken（接口） 需要转化为 UsernamePasswordToken（实现类）
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;

        //用户名
        String username = userToken.getUsername();


        PmUser pmUser = null;
        SimpleAuthenticationInfo simpleInfo = null;
        try {


            EntityWrapper wrapper = new EntityWrapper<PmUser>();
            wrapper.eq("user_name", username);
            pmUser = userService.selectOne(wrapper);

            if (null == pmUser) {
                throw new CgException("用户不存在");

            }
            PmUserVO user = new PmUserVO();
            Father2Son.Copy(pmUser, user);


//盐值为
//         simpleInfo = new SimpleAuthenticationInfo(user.getUserName(), user.getPassword(), getName());
            simpleInfo = new SimpleAuthenticationInfo(user, user.getPassword(), new ShiroByteSource(user.getUserName()), getName());


            if (user == null) {
                //没有该用户名
                throw new UnknownAccountException();
            } else if (!simpleInfo.getCredentials().equals(user.getPassword())) {
                //密码错误
                throw new IncorrectCredentialsException();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //身份验证通过,返回一个身份信息

        return simpleInfo;
    }


    @Override
    protected void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        Cache c = getAuthenticationCache();
        logger.info("清除【认证】缓存之前");
        if (null != c) {
            for (Object o : c.keys()) {
                logger.info(o + " , " + c.get(o));
            }
            super.clearCachedAuthenticationInfo(principals);
            logger.info("调用父类清除【认证】缓存之后");
            for (Object o : c.keys()) {
                logger.info(o + " , " + c.get(o));
            }

            // 添加下面的代码清空【认证】的缓存
            PmUser user = (PmUser) principals.getPrimaryPrincipal();
            SimplePrincipalCollection spc = new SimplePrincipalCollection(user.getUserName(), getName());
            super.clearCachedAuthenticationInfo(spc);
            logger.info("添加了代码清除【认证】缓存之后");
            int cacheSize = c.keys().size();
            logger.info("【认证】缓存的大小:" + c.keys().size());
            if (cacheSize == 0) {
                logger.info("说明【认证】缓存被清空了。");
            }
        }

    }

    @Override
    protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        logger.info("清除【授权】缓存之前");
        Cache c = getAuthorizationCache();
        if (null != c) {

            for (Object o : c.keys()) {
                logger.info(o + " , " + c.get(o));
            }

            super.clearCachedAuthorizationInfo(principals);
            logger.info("清除【授权】缓存之后");
            int cacheSize = c.keys().size();
            logger.info("【授权】缓存的大小:" + cacheSize);

            for (Object o : c.keys()) {
                logger.info(o + " , " + c.get(o));
            }
            if (cacheSize == 0) {
                logger.info("说明【授权】缓存被清空了。");
            }
        }

    }


}
